/*
 *  Class name: PlayerManagedBean.java
 *  Version: 1.0
 *  Date: 22.11.2013
 */
package cz.muni.fi.pa165.soccergamesarchive.managedbeans.entity;

import cz.muni.fi.pa165.soccergamesarchive.businesslayer.dtos.PlayerDTO;
import cz.muni.fi.pa165.soccergamesarchive.businesslayer.dtos.PlayerDetailDTO;
import cz.muni.fi.pa165.soccergamesarchive.businesslayer.dtos.TeamDTO;
import cz.muni.fi.pa165.soccergamesarchive.businesslayer.services.PlayerServiceBeanLocal;
import cz.muni.fi.pa165.soccergamesarchive.businesslayer.services.TeamServiceBeanLocal;
import cz.muni.fi.pa165.soccergamesarchive.datamodels.entity.TeamDataModel;
import cz.muni.fi.pa165.soccergamesarchive.managedbeans.application.ActionState;
import cz.muni.fi.pa165.soccergamesarchive.managedbeans.application.DialogChooserListenable;
import cz.muni.fi.pa165.soccergamesarchive.managedbeans.application.NavigationMapper;
import cz.muni.fi.pa165.soccergamesarchive.managedbeans.application.NavigationMenuBean;
import cz.muni.fi.pa165.soccergamesarchive.managedbeans.entity.handlers.table.PlayerArrangeableTableHandler;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.enterprise.context.SessionScoped;
import javax.inject.Inject;
import javax.inject.Named;

import static cz.muni.fi.pa165.soccergamesarchive.utils.LabelTextHandler.getActionDescriptionText;
import static cz.muni.fi.pa165.soccergamesarchive.utils.LabelTextHandler.getFullActionDescriptionText;
import static java.lang.Long.valueOf;
import static java.util.Collections.sort;

/**
 *
 * @author Michal Ďuriš
 */
@Named(value = "playerManagedBean")
@SessionScoped
public class PlayerManagedBean implements Serializable, DialogChooserListenable {
    
    private static final long serialVersionUID = 1L;
    
    private static final String DEFAULT_ACTION_INVOCATION_LOCATION = "DEFAULT";
    
    @EJB
    private PlayerServiceBeanLocal playerServiceBean;
    
    @EJB
    private TeamServiceBeanLocal teamServiceBean;
    
    @Inject
    private PlayerArrangeableTableHandler tableHandler;
    
    @Inject
    private NavigationMenuBean menuBean;
    
    private TeamDataModel teamDataModel;
    
    private TeamDTO playersTeam;
    
    private PlayerDetailDTO currentlyDetailedPlayer;
    
    private PlayerDTO currentlyManagedPlayer;
    
    private ActionState currentState;
    
    private String actionInvocationLocation;
    
    private int mouseX, mouseY;

    /**
     * Creates a new instance of PlayerManagedBean
     */
    public PlayerManagedBean() {
    }
    
    @PostConstruct
    public void init() {
        
        teamDataModel = new TeamDataModel(teamServiceBean);
        teamDataModel.getFilterMap().put("name", "");
        teamDataModel.getOrderMap().put("name", Boolean.TRUE);
        
        currentlyManagedPlayer = new PlayerDTO();
        
        currentState = ActionState.NONE;
        actionInvocationLocation = DEFAULT_ACTION_INVOCATION_LOCATION;
    }
    
    public ActionState getCurrentState() {
        return currentState;
    }
    
    public void setCurrentState(ActionState currentState) {
        this.currentState = currentState;
    }
    
    public String getActionInvocationLocation() {
        return actionInvocationLocation;
    }
    
    public void setActionInvocationLocation(String actionInvocationLocation) {
        this.actionInvocationLocation = actionInvocationLocation;
    }
    
    public PlayerArrangeableTableHandler getTableHandler() {
        return tableHandler;
    }
    
    public PlayerDetailDTO getCurrentlyDetailedPlayer() {
        return currentlyDetailedPlayer;
    }
    
    public void setCurrentlyDetailedPlayer(
            PlayerDetailDTO currentlyDetailedPlayer) {
        this.currentlyDetailedPlayer = currentlyDetailedPlayer;
    }
    
    public PlayerDTO getCurrentlyManagedPlayer() {
        return currentlyManagedPlayer;
    }
    
    public void setCurrentlyManagedPlayer(PlayerDTO currentlyManagedPlayer) {
        this.currentlyManagedPlayer = currentlyManagedPlayer;
    }
    
    public void setPlayersTeam(TeamDTO playersTeam) {
        this.playersTeam = playersTeam;
    }
    
    public TeamDTO getPlayersTeam() {
        return playersTeam;
    }
    
    @Override
    public Object getDataModel() {
        return teamDataModel;
    }
    
    @Override
    public Map<String, Object> getFilterMap() {
        return teamDataModel.getFilterMap();
    }
    
    @Override
    public void storeResult(String resultName, Object result) {
        
        if (result != null && result instanceof TeamDTO) {
            
            TeamDTO selectedTeam = (TeamDTO) result;
            
            if (!(currentlyManagedPlayer.getTeam().equals(selectedTeam))) {
                
                currentlyManagedPlayer.setTeam(selectedTeam);
            }
        }
        
        teamDataModel.getFilterMap().put("name", "");
    }
    
    private boolean isThisPlayersTeam() {
        return playersTeam.equals(currentlyManagedPlayer.getTeam());
    }
    
    public String getEditorPanelTitle() {
        
        String title;
        
        try {
            title = getFullActionDescriptionText(currentState,
                    NavigationMapper.PLAYER_MODULE);
        } catch (IllegalStateException e) {
            title = "ERROR";
            //TODO: SOME ERROR STATE DIALOG WINDOW
        }
        
        return title;
    }
    
    public String getEditorButtonLabel() {
        
        String label;
        
        try {
            label = getActionDescriptionText(currentState);
        } catch (IllegalStateException e) {
            label = "ERROR";
            //TODO: SOME ERROR STATE DIALOG WINDOW
        }
        
        return label;
    }
    
    public List<Integer> getAvailableShirtNumbers() {
        
        List<Integer> availableShirtNumbers = new ArrayList<>();
        
        if (currentlyManagedPlayer.getTeam().getId() != null) {
            availableShirtNumbers = teamServiceBean.getAvaliableShirtNumbers(
                    currentlyManagedPlayer.getTeam());
            
            if (currentState == ActionState.EDIT && isThisPlayersTeam()) {
                availableShirtNumbers.add(
                        currentlyManagedPlayer.getShirtNumber());
                sort(availableShirtNumbers);
            }
        }
        
        return availableShirtNumbers;
    }
    
    public String processActionAndRedirect(ActionState state) {
        
        switch (state) {
            case ADD:
                currentState = ActionState.ADD;
                currentlyManagedPlayer = new PlayerDTO();
                currentlyDetailedPlayer = null;
                playersTeam = null;
                
                return menuBean.goToLocation(NavigationMapper.PLAYER_MODULE,
                        NavigationMapper.ADD_SECTION);
            case EDIT:
                currentState = ActionState.EDIT;
                currentlyDetailedPlayer = null;
                
                return menuBean.goToLocation(NavigationMapper.PLAYER_MODULE,
                        NavigationMapper.EDIT_SECTION);
            case VIEW:
                currentState = ActionState.VIEW;
                currentlyManagedPlayer = new PlayerDTO();
                currentlyDetailedPlayer = null;
                playersTeam = null;
                
                return getInvocationLocation();
            default:
                System.err.println("UNHANDLED ACTION = NO REDIRECT");
        }
        
        return "";
    }
    
    private String getInvocationLocation() {
        
        if (actionInvocationLocation != null
            && "team".equals(actionInvocationLocation.trim().toLowerCase(
                                Locale.ROOT))) {
            
            actionInvocationLocation = DEFAULT_ACTION_INVOCATION_LOCATION;
            
            return menuBean.goToLocation(NavigationMapper.TEAM_MODULE,
                    NavigationMapper.VIEW_SECTION);
        }
        
        return menuBean.goToLocation(NavigationMapper.PLAYER_MODULE,
                NavigationMapper.VIEW_SECTION);
    }
    
    public String handleAction() {
        
        switch (currentState) {
            case ADD:
                if (addPlayer()) {
                    
                    return menuBean.goToLocation(NavigationMapper.PLAYER_MODULE,
                            NavigationMapper.VIEW_SECTION);
                }
                break;
            case EDIT:
                if (changePlayer()) {
                    
                    return getInvocationLocation();
                }
                break;
            case DELETE:
                removePlayer();
                break;
            default:
                System.err.println("UNHANDLED ACTION");
        }
        
        return "";
    }
    
    private boolean addPlayer() {
        try {
            
            playerServiceBean.addPlayer(currentlyManagedPlayer);
        } catch (RuntimeException ex) {
            return false;
        }
        return true;
    }
    
    private boolean changePlayer() {
        try {
            
            playerServiceBean.changePlayer(currentlyManagedPlayer);
        } catch (RuntimeException ex) {
            return false;
        }
        return true;
    }
    
    private void removePlayer() {
        try {
            
            playerServiceBean.removePlayer(currentlyManagedPlayer);
            
            if (currentlyDetailedPlayer != null
                && Objects.equals(currentlyManagedPlayer.getId(),
                            currentlyDetailedPlayer.getId())) {
                
                currentlyDetailedPlayer = null;
            }
            
            if (actionInvocationLocation != null
                && "team".equals(actionInvocationLocation.trim()
                            .toLowerCase(
                                    Locale.ROOT))) {
                
                playersTeam.getPlayers().remove(currentlyManagedPlayer);
                actionInvocationLocation = DEFAULT_ACTION_INVOCATION_LOCATION;
            }
            
        } catch (RuntimeException ex) {
            //TODO: LOGGER
            System.err.println("Exception thrown in " + getClass().getName()
                               + " in removePlayer method. Exception: " + ex);
        }
    }
    
    public void rowKeyListener(Object rowKey, int mouseX, int mouseY) {
        
        this.mouseX = mouseX;
        this.mouseY = mouseY;
        
        Long id = valueOf((String) rowKey);
        
        if (currentlyDetailedPlayer != null
            && Objects.equals(currentlyDetailedPlayer.getId(), id)) {
            
            currentlyDetailedPlayer = null;
        } else {
            currentlyDetailedPlayer = playerServiceBean.getPlayerDetail(id);
            currentlyDetailedPlayer.setId(id);
        }
    }
    
    public int getMouseX() {
        return mouseX;
    }
    
    public int getMouseY() {
        return mouseY;
    }
    
}
